<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
	<link rel="stylesheet" href="./css/style.css">
</head>
<body>

<button onclick="obj.fn('111', '222')">点我防抖</button>
<button onclick="obj.fn2('111', '222')">点我节流</button>

<script>

	const fn = debounce(function(a, b) {
    console.log('函数被执行了..., 参数: ', a, b);
    console.log('函数执行时的this--->', this);
  }, 1000, false)
	
	const fn2 = throttle(function(a, b) {
    console.log('节流函数的this--->', this);
  }, 1000)

  const obj = {
    name: '我是obj',
    fn: fn,
	  fn2: fn2
  }
	
  // 防抖: 连续触发函数时, 只执行第一次或最后一次
	function debounce(fn, delay, immediate) {
    let timer;
    return function(...args) {
      const ctx = this; // 这里的this指向外面实际函数调用者
      // console.log(`请等待${delay}毫秒...`);
	    if(immediate && !timer) fn.apply(ctx, args)
      clearTimeout(timer)
      timer = setTimeout(function() {
        timer = null;
        if(!immediate) fn.apply(ctx, args)
      }, delay)
    }
	}
  
  // 节流: 连续触发函数时, 需度过"冷却"时间再执行
	function throttle(fn, cd) {
    let timer;
    return function(...args) {
      let last = timer;
      let now = Date.now();
      if (!last) { //第一次执行
        timer = now; // 更新最后执行的时间
        fn.apply(this, args);
	      return;
      }
      if(last + cd > now) return;
      timer = now; // 更新最后执行的时间
      fn.apply(this, args); // 不用apply的话, this指向的就是window了
    }
	}

  let debounceTimer = null
  function debounceB(callback, duration, isFirstExecution) {
    return function(...args) {
      const ctx = this;
      console.log('debounceTimer--->', debounceTimer);
      const delay = function() {
        debounceTimer = null
        if (!isFirstExecution) callback.apply(ctx, args)
      }
      const executeNow = isFirstExecution && !debounceTimer
      clearTimeout(debounceTimer)
      debounceTimer = setTimeout(delay, duration)
      if (executeNow) callback.apply(ctx, args)
    }
  }
	
</script>

</body>
</html>
